﻿//GOCW主函数文件
//jsxyhelu 
//《如何使用C#(.NET)调用自己编写OpenCV算法的CLR(DLL)类库（Visual Studio 2017）》202012
/*
    1、C++/CLI里的new等于C++里的new, gcnew等于C#里的new
　　2、原生指针用*表示,托管引用使用^表示 如: Stream^ stream = gcnew Stream();
　　3、array<unsigned char>^ 等于 System.Byte[]，这可以用来传递很多东西
　　4、pin_ptr关键字能把托管引用转换为原生指针:
　　如: pin_ptr<BYTE> pBytes = & byteArray[0];
　　然后pBytes就可以当作原生的BYTE* 使用了. 
　　等代码执行完pBytes的有效范围,byteArray就会恢复可被GC处理的状态

*/

#include "pch.h"
#include "GOCW.h"
#include "opencv.hpp"

#using <system.drawing.dll>
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace GOCW;

using namespace std;
using namespace cv;

#define  VP  vector<cv::Point>  //用VP符号代替 vector<point>
//////////////////////////////////////////////////////////Helper函数/////////////////////////////////////////////
//将Mat转换为BitMap
System::Drawing::Bitmap^ MatToBitmap(const cv::Mat& img)
{
	if (img.type() != CV_8UC3)
	{
		throw gcnew NotSupportedException("Only images of type CV_8UC3 are supported for conversion to Bitmap");
	}
	//create the bitmap and get the pointer to the data
	PixelFormat fmt(PixelFormat::Format24bppRgb);
	Bitmap ^bmpimg = gcnew Bitmap(img.cols, img.rows, fmt);
	BitmapData ^data = bmpimg->LockBits(System::Drawing::Rectangle(0, 0, img.cols, img.rows), ImageLockMode::WriteOnly, fmt);
	Byte *dstData = reinterpret_cast<Byte*>(data->Scan0.ToPointer());
	unsigned char *srcData = img.data;
	for (int row = 0; row < data->Height; ++row)
	{
		memcpy(reinterpret_cast<void*>(&dstData[row*data->Stride]), reinterpret_cast<void*>(&srcData[row*img.step]), img.cols*img.channels());
	}
	bmpimg->UnlockBits(data);
	return bmpimg;
}
///////////////////////////////////////////////////////测试函数实现/////////////////////////////////////////////
//1.传递图像
Bitmap^  GOCWClass::testMethod(cli::array<unsigned char>^ pCBuf1)
{
	////////////////////////////////将输入cli::array<unsigned char>转换为cv::Mat/////////////////////////
	pin_ptr<System::Byte> p1 = &pCBuf1[0];
	unsigned char* pby1 = p1;
	cv::Mat img_data1(pCBuf1->Length, 1, CV_8U, pby1);
	cv::Mat img_object = cv::imdecode(img_data1, cv::IMREAD_UNCHANGED);
	if (!img_object.data)
		return nullptr;
	////////////////////////////////////////////OpenCV的算法处理过程////////////////////////////////////
	Mat draw = img_object.clone();
	cvtColor(draw, draw, COLOR_BGR2GRAY);
	cvtColor(draw, draw, COLOR_GRAY2BGR);
	/////////////////////////将cv::Mat转换为Bitmap(只能传输cv_8u3格式数据）///////////////////////////////
	if (!draw.data)
		return nullptr;
	Bitmap^ bitmap = MatToBitmap(draw);
	return bitmap;
}
//2.引用传递int
int  GOCWClass::allTest(int a, int b, int* c)
{
	*c = a + b;
	return *c;
}
////3.引用传递字符串
System::String^ GOCWClass::allTestStr(System::String^ inputStr)
{
	System::String^ retstr = inputStr + "fsdfsdf";
	return retstr;
}
/////////////////////////////////////////////////////////业务函数实现/////////////////////////////////////////////
Bitmap^  GOCWClass::fetchresult(cli::array<unsigned char>^ pCBuf1, int* errorCode)
{
	////////////////////////////////将输入cli::array<unsigned char>转换为cv::Mat/////////////////////////
	pin_ptr<System::Byte> p1 = &pCBuf1[0];
	unsigned char* pby1 = p1;
	cv::Mat img_data1(pCBuf1->Length, 1, CV_8U, pby1);
	cv::Mat img_object = cv::imdecode(img_data1, IMREAD_UNCHANGED);
	if (!img_object.data)
		return nullptr;
	////////////////////////////////////////////OpenCV的算法处理过程////////////////////////////////////
	Mat src = img_object.clone();
	Mat draw = img_object.clone();
	cvtColor(draw, draw, COLOR_BGR2GRAY);
	cvtColor(draw, draw, COLOR_GRAY2BGR);
	/////////////////////////将cv::Mat转换为Bitmap(只能传输cv_8u3格式数据）///////////////////////////////
	//0 Pass 1 NG
	bool bError = true;
	if (bError == true)
	{
		*errorCode = 1;
	}
	else {
		*errorCode = 0;
	}
	if (!draw.data)
		return nullptr;
	Bitmap^ bitmap = MatToBitmap(draw);
	return bitmap;
}



